#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <termios.h>
#include <stdlib.h>
#include "serial.h"

int set_opt(int fd,int nSpeed, int nBits, char nEvent, int nStop)
{
    struct termios newtio,oldtio;
    if  ( tcgetattr( fd,&oldtio)  !=  0) 
    { 
        perror("SetupSerial 1");
        return -1;
    }
    bzero( &newtio, sizeof( newtio ) );
    newtio.c_cflag  |=  CLOCAL | CREAD; 
    newtio.c_cflag &= ~CSIZE; 

    switch( nBits )
    {
    case 7:
        newtio.c_cflag |= CS7;
        break;
    case 8:
        newtio.c_cflag |= CS8;
        break;
    }

    switch( nEvent )
    {
    case 'O':                     //奇校验
        newtio.c_cflag |= PARENB;
        newtio.c_cflag |= PARODD;
        newtio.c_iflag |= (INPCK | ISTRIP);
        break;
    case 'E':                     //偶校验
        newtio.c_iflag |= (INPCK | ISTRIP);
        newtio.c_cflag |= PARENB;
        newtio.c_cflag &= ~PARODD;
        break;
    case 'N':                    //无校验
        newtio.c_cflag &= ~PARENB;
        break;
    }

switch( nSpeed )
    {
    case 300:
        cfsetispeed(&newtio, B300);
        cfsetospeed(&newtio, B300);
        break;	
    case 600:
        cfsetispeed(&newtio, B600);
        cfsetospeed(&newtio, B600);
        break;		
    case 1200:
        cfsetispeed(&newtio, B1200);
        cfsetospeed(&newtio, B1200);
        break;			
    case 2400:
        cfsetispeed(&newtio, B2400);
        cfsetospeed(&newtio, B2400);
        break;
    case 4800:
        cfsetispeed(&newtio, B4800);
        cfsetospeed(&newtio, B4800);
        break;
    case 9600:
        cfsetispeed(&newtio, B9600);
        cfsetospeed(&newtio, B9600);
        break;
     case 19200:
        cfsetispeed(&newtio, B19200);
        cfsetospeed(&newtio, B19200);
        break;       
     case 38400:
        cfsetispeed(&newtio, B38400);
        cfsetospeed(&newtio, B38400);
        break;  
     case 57600:
        cfsetispeed(&newtio, B57600);
        cfsetospeed(&newtio, B57600);
        break;      
    case 115200:
        cfsetispeed(&newtio, B115200);
        cfsetospeed(&newtio, B115200);
        break;
    default:
        printf("sorry! [%d bps] is not support ,Set default 9600bps now!\n",nSpeed);
        cfsetispeed(&newtio, B9600);
        cfsetospeed(&newtio, B9600);
        break;
    }
    if( nStop == 1 )
    {
        newtio.c_cflag &=  ~CSTOPB;
    }
    else if ( nStop == 2 )
    {
        newtio.c_cflag |=  CSTOPB;
    }
    newtio.c_cc[VTIME]  = 0;
    newtio.c_cc[VMIN] = 0;
    tcflush(fd,TCIFLUSH);
    if((tcsetattr(fd,TCSANOW,&newtio))!=0)
    {
        perror("com set error");
        return -1;
    }
    printf("set done!\n");
    return 0;
}

int open_port(char *dev)
{
    //char *dev[]={"/dev/ttyO1","/dev/ttyO2","/dev/ttyO3"};
	long  vdisable;
	int fd = -1;
	fd = open( dev, O_RDWR|O_NOCTTY); 
	if (-1 == fd)
	{
		perror("Can't Open Serial Port");
		return(-1);
	}
	else 
	{
		printf("open %s ok\n",dev);
	}

	if(fcntl(fd, F_SETFL, 0)<0)
	{
		printf("fcntl failed!\n");
	}
	else
	{
		printf("fcntl=%d\n",fcntl(fd, F_SETFL,0));
	}
	if(isatty(STDIN_FILENO)==0)
	{
		printf("standard input is not a terminal device\n");
	}
	else
	{
		printf("isatty success!\n");
	}
	printf("fd-open=%d\n",fd);
	return fd;
}

int init_serail(char * dev,int nSpeed, int nBits, char nEvent, int nStop)
{	
	int fd = -1,i=0;
	fd = open_port(dev);
	if(fd < 0){
		perror("init_serail open_port failed!");
		return fd;
	}
	
	if((i=set_opt(fd,nSpeed,nBits,nEvent,nStop))<0){//设置串口
		perror("set_opt error");
		return -1;
	}
	return fd;
}

int send_data(int fd,char * in_data,int len)
{
	int n = 0;
	if(!in_data || len < 1){
		printf("send_data,error param\r\n");	
		return -1;
	}
	n = write(fd, in_data, len);
	printf("send length:%d,data:%s",len,in_data);
	return n;
}

int recv_data(int fd,char * out_data,int needlen)
{
	int  nread = 0;
	if(!out_data|| needlen < 1){
		printf("recv_data,error param\r\n");	
		return -1;
	}
	nread=read(fd,out_data,needlen);
	if(nread > 0){
		printf("recv data:%s,length:%d\r\n",out_data,nread);
	}else{
		printf("recv no data");
	}
	return nread;
}